package com.cheejee.goodscenter.service.impl;

import static com.cheejee.goodscenter.util.StaticField.GOODS_PIC_SPLIT;

import java.security.acl.Group;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import com.cheejee.goodscenter.dao.GoodsMapper;
import com.cheejee.goodscenter.module.dto.GoodsDto;
import com.cheejee.goodscenter.module.entity.Goods;
import com.cheejee.goodscenter.module.entity.GoodsBrandProperties;
import com.cheejee.goodscenter.module.entity.GoodsCategoryProperties;
import com.cheejee.goodscenter.module.entity.GoodsCustomProperties;
import com.cheejee.goodscenter.module.entity.GoodsSpecific;
import com.cheejee.goodscenter.service.GoodsBrandPropertiesService;
import com.cheejee.goodscenter.service.GoodsCategoryPropertiesService;
import com.cheejee.goodscenter.service.GoodsCustomPropertiesService;
import com.cheejee.goodscenter.service.GoodsService;
import com.cheejee.goodscenter.service.GoodsSpecificService;
import com.cheejee.goodscenter.service.SkuService;
import com.cheejee.goodscenter.service.exception.CheckException;
import com.cheejee.goodscenter.service.exception.DataNotExistException;
import com.cheejee.goodscenter.service.exception.DuplicateException;
import com.cheejee.goodscenter.validated.Check;
import com.cheejee.goodscenter.validated.InsertGroup;
import com.cheejee.goodscenter.validated.UpdateGroup;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.spring.SpringUtil;

/**
 * @author CARRY
 * @Date 2020年10月27日上午12:13:06
 */
@Service
public class GoodsServiceImpl implements GoodsService {

	@Resource
	private GoodsMapper gm;

	@Resource
	private SkuService ss;

	@Resource
	private GoodsSpecificService gss;

	@Resource
	private GoodsBrandPropertiesService gbps;

	@Resource
	private GoodsCategoryPropertiesService gcps;

	@Resource
	private GoodsCustomPropertiesService gmps;

	@Override
	public Goods queryGoodsById(Long id) {

		return gm.selectByPrimaryKey(id);
	}

	@Override
	public GoodsDto queryGoodsInfo(@NotNull(message = "商品ID不能为空") Long id) {
		Goods g = gm.selectByPrimaryKey(id);
		if (g == null) {
			return null;
		}
		
		List<String> pic = null;
		if(g.getPics() != null) {
			pic = Arrays.asList(g.getPics().split(GOODS_PIC_SPLIT));
		}

		return GoodsDto.builder().
				id(g.getId())
				.brandId(g.getBrandId())
				.categoryId(g.getCategoryId())
				.goodsName(g.getGoodsName())
				.subtitle(g.getSubtitle())
				.pics(pic)
				.unit(g.getUnit())
				.isOn(g.getIsOn())
				.isDetelete(g.getIsDetelete())
				.sale(g.getSale())
				.webDetail(g.getWebDetail())
				.mobileDetail(g.getMobileDetail())
				.createTime(g.getCreateTime())
				.updateTime(g.getUpdateTime())
				.specific(gss.queryGoodsSpecific(g.getId(), null, null, 0, 0))
				.sku(ss.querySkuDto(g.getId(), null, null, 0, 0).getList())
				.brandProperties(gbps.queryGoodsBrandProperties(g.getId(), null, null, 0, 0))
				.categoryProperties(gcps.queryGoodsCategoryProperties(g.getId(), null, null, 0, 0))
				.customProperties(gmps.queryGoodsCustomProperties(g.getId(), null, 0, 0)).build();
	}

	@Override
	public Page<Goods> queryGoods(Integer brandId, Integer categoryId, String goodsName, Boolean isOn, Boolean isDetelete, int pageNum, int pageSize) {

		return PageHelper.startPage(pageNum, pageSize).doSelectPage(() -> gm.selectBySelective(brandId, categoryId, goodsName, isOn, isDetelete));
	}

	@Override
	public Page<Goods> queryGoodsOrderBySale(boolean collation, int pageNum, int pageSize) {
		String order = "desc";

		if (collation) {
			order = "asc";
		}

		PageHelper.startPage(pageNum, pageSize);
		return (Page<Goods>) gm.selectByOrder("sale " + order);
	}

	@Override
	public Page<Goods> queryGoodsOrderByTime(boolean collation, int pageNum, int pageSize) {
		String order = "desc";

		if (collation) {
			order = "asc";
		}

		PageHelper.startPage(pageNum, pageSize);
		return (Page<Goods>) gm.selectByOrder("create_time " + order);
	}

	@Override
	@Check(message = "添加的商品不能为空", group = InsertGroup.class)
	public int addGoods(Goods goods) {

		if (!CollectionUtil.isEmpty(gm.selectBySelective(null, null, goods.getGoodsName(), null, null))) {
			throw new DuplicateException("商品名称已存在");
		}

		goods.setPublicityPic(goods.getPics().split(GOODS_PIC_SPLIT)[0]);// 设置商品宣传图
		goods.setCreateTime(new Date());
		goods.setUpdateTime(new Date());

		// TODO： 增加销量更新的定时任务。

		return gm.insertSelective(goods);
	}

	@Override
	@Transactional
	@Check(message = "添加的商品不能为空", group = InsertGroup.class)
	public int addGoodsInfo(GoodsDto goods) {
		Goods g = goods.toGoods();
		g.setCreateTime(new Date());
		g.setUpdateTime(new Date());
		gm.insertSelective(g);
		goods.setId(g.getId());
		
		List<GoodsSpecific> ls = goods.getSpecific();
		if (!CollectionUtil.isEmpty(ls)) {
			ls.forEach(i -> i.setGoodsId(g.getId()));
			gss.addGoodsSpecific(ls);
		}
		
		if (!CollectionUtil.isEmpty(goods.getSku())) {
			ss.addSku(g.getId(), goods.getSku());
		}

		List<GoodsBrandProperties> bp = goods.getBrandProperties();
		if (!CollectionUtil.isEmpty(bp)) {
			bp.forEach(i -> i.setGoodsId(g.getId()));
			gbps.addGoodsBrandProperties(bp);
		}

		List<GoodsCategoryProperties> cp = goods.getCategoryProperties();
		if (!CollectionUtil.isEmpty(cp)) {
			cp.forEach(i -> i.setGoodsId(g.getId()));
			gcps.addGoodsCategoryProperties(cp);
		}

		List<GoodsCustomProperties> mp = goods.getCustomProperties();
		if (!CollectionUtil.isEmpty(mp)) {
			mp.forEach(i -> i.setGoodsId(g.getId()));
			gmps.addGoodsCustomProperties(mp);
		}

		return 1;
	}

	@Override
	@Check(message = "修改的商品不能为空", group = UpdateGroup.class)
	public int changeGoods(Goods goods) {
		checkExist(goods.getId());
		goods.setUpdateTime(Date.from(Instant.now()));
		goods.setCreateTime(null);

		return gm.updateByPrimaryKeySelective(goods);
	}

	@Override
	@Transactional
	@Check(message = "修改的商品不能为空", group = UpdateGroup.class)
	public int changeGoodsInfo(GoodsDto goods) {

		Long goodsId = goods.getId();
		if(gm.selectByPrimaryKey(goodsId) == null) {
			throw new DataNotExistException("商品不存在");
		}
		
		// 更新商品基本信息
		Goods gd = goods.toGoods();
		gd.setUpdateTime(new Date());
		gd.setCreateTime(null);
		gm.updateByPrimaryKeySelective(gd);

		// 更新商品规格
		changeGoodsSpecific(goods.getSpecific());

		// 更新商品SKU
		if (!CollectionUtil.isEmpty(goods.getSku())) {
			ss.changeGoodsSku(goodsId, goods.getSku());
		}

		// 更新商品属性
		List<GoodsCustomProperties> mp = goods.getCustomProperties();
		if (!CollectionUtil.isEmpty(mp)) {
			Long[] bpId = mp.stream().map(i -> {
				i.setGoodsId(goodsId);
				return i;
			}).map(i -> i.getId()).toArray(Long[]::new);
			gmps.deleteGoodsCustomProperties(bpId);
			gmps.addGoodsCustomProperties(mp);
		}
		
		List<GoodsBrandProperties> bp = goods.getBrandProperties();
		if (!CollectionUtil.isEmpty(bp)) {
			Long[] bpId = bp.stream().map(i -> {
				i.setGoodsId(goodsId);
				return i;
			}).map(i -> i.getId()).toArray(Long[]::new);
			gbps.deleteGoodsBrandProperties(bpId);
			gbps.addGoodsBrandProperties(bp);
		}

		List<GoodsCategoryProperties> cp = goods.getCategoryProperties();
		if (!CollectionUtil.isEmpty(cp)) {
			Long[] cpId = cp.stream().map(i -> {
				i.setGoodsId(goodsId);
				return i;
			}).map(i -> i.getId()).toArray(Long[]::new);
			gcps.deleteGoodsCategoryProperties(cpId);
			gcps.addGoodsCategoryProperties(cp);
		}

		return 1;
	}

	@Override
	public int deleteGoods(Long... id) {
		for(Long i : id) {
			Goods g = gm.selectByPrimaryKey(i);
			if(g != null) {
				g.setIsDetelete(true);
				gm.updateByPrimaryKeySelective(g);
			}
		}
		return id.length;
	}

	@Override
	public void taskUpAndDown(Date date, Boolean type, Integer... id) {
		// TODO: 增加定时上下架的定时任务。
	}

	private void checkExist(Long id) {
		if (gm.selectByPrimaryKey(id) == null) {
			throw new DataNotExistException("商品不存在");
		}
	}

	private void changeGoodsSpecific(List<GoodsSpecific> specific) {
		if (CollectionUtil.isEmpty(specific)) {
			return;
		}

		Long goodsId = 0L;
		List<GoodsSpecific> addList = new ArrayList<>();
		List<GoodsSpecific> list = new ArrayList<>(specific);

		for (GoodsSpecific s : specific) {

			if (goodsId.equals(0L)) {
				goodsId = s.getGoodsId();
			} else if (!goodsId.equals(s.getGoodsId())) {
				throw new CheckException("商品规格信息不正确");
			}

			Long id = s.getId();
			if (id == null) {
				addList.add(s);
				list.remove(s);
			} else {
				gss.changeGoodsSpecific(s);
			}
		}

		List<Long> o = gss.queryGoodsSpecific(goodsId, null, null, 0, 0).stream().map(i -> i.getId()).collect(Collectors.toList());
		List<Long> n = list.stream().map(i -> i.getId()).collect(Collectors.toList());
		o.removeAll(n);

		if (addList.size() != 0) {
			gss.addGoodsSpecific(addList);
		}

		if (o.size() != 0) {
			gss.deleteGoodsSpecific(o.toArray(new Long[o.size()]));
		}
	}

}
